/***************************************************************************
 *   Copyleft 2008-2009 by												   *
 *	 Iwanicki Krzysztof													   *
 *   <gamma.mini.pw.edu.pl/~iwanickik>									   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 ***************************************************************************/
#include "./vGlApi.h"
#include "./vWin32Timer.h"
#include "../State/vStates.h"
#include "../Viewport/vViews.h"
#include "../Renderer/vGlPainter.h"
#include "../Renderer/vGlRenderer.h"
#include "../vEngine3D.h"
#include "../../Macros/vMacros.h"
#include "../Geometry/vGlVertexBufferManager.h"


namespace Vendetta {
	vGlApi::vGlApi(): vApi() {
		mName = "OpenGL";
		mpGlExtensionManager = vNull;

	}

	vGlApi::~vGlApi() {
	}

	vBool vGlApi::init() {
		// Important: Renderer must be Initialized after View! - see its constructor
		mpView = new vGlView;
		mpState = new vGlState;
		mpPainter = new vGlPainter;
		mpRenderer = new vGlRenderer;
		mpTimer = new vWin32Timer;
		mpVertexBufferManager = new vGlVertexBufferManager;

		return true;
	}

	vVoid vGlApi::kill() {
		vDelete(mpTimer);
		vDelete(mpVertexBufferManager);
		vDelete(mpRenderer);
		vDelete(mpPainter);
		vDelete(mpState);
		vDelete(mpView);
		vDelete(mpGlExtensionManager);
	}

	vVoid vGlApi::Update() {
		vApi::Update();
	}

	// Returns Win32 specific OpenGL object
	//vVoid* vGlApi::NewObject(const vInt objectmName) {
	//	switch (objectmName) {
	//		case API_OBJECT_TEXTURE_CREATOR : return monsterNew cGLTextureCreator;
	//		case API_OBJECT_FONT_CREATOR : return monsterNew cGLFontCreator;
	//	}
	//	return vNull;
	//}

	// Reads color buffer
	vVoid vGlApi::readColorBuffer(vUInt8* pixels) const {
		glReadPixels(0, 0, vEngine3D::InstancePtr()->MainWindowPtr()->Width(), 
			vEngine3D::InstancePtr()->MainWindowPtr()->Height(), 
			GL_RGB, GL_UNSIGNED_BYTE, pixels); V_GL_ASSERT
	}

	// Handles OpenGL errors
	vVoid vGlApi::handleErrors() {
		GLenum GLError;
		static vString errorsString;

		errorsString.Clear();
		while ((GLError = glGetError()) != GL_NO_ERROR) {
			if (errorsString.Length() > 0) {
				errorsString += ", ";
			}

			switch (GLError) {
				case GL_INVALID_ENUM:
					errorsString += "GL_INVALID_ENUM";
					break;
				case GL_INVALID_VALUE:
					errorsString += "GL_INVALID_VALUE";
					break;
				case GL_INVALID_OPERATION:
					errorsString += "GL_INVALID_OPERATION";
					break;
				case GL_STACK_OVERFLOW:
					errorsString += "GL_STACK_OVERFLOW";
					break;
				case GL_STACK_UNDERFLOW:
					errorsString += "GL_STACK_UNDERFLOW";
					break;
				case GL_OUT_OF_MEMORY:
					errorsString += "GL_OUT_OF_MEMORY";
					break;
				default:
					//errorsString.append("[Unknown: 0x%X]", GLError);
					break;
			}
		}

		if (errorsString.Length() > 0) {
			LOGS_ERROR("Following OpenGL errors were caught: %s", errorsString.ToConstCharPtr());
			//throw cException("Following OpenGL errors were caught: %s", (const cChar*) errorsString);
		}
	}
}